﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KiDS_Bootstrap
{
	/// <summary>
	/// Klasa koja predstavlja CMD_BOOTSTRAP_REGISTER_SERVENT komandu
	/// </summary>
	public class BootstrapRegisterServentCommand : Command
	{
		private short _port;
		private string _location, _address;
		readonly bool _correct; 
		private readonly Bootstrap _bootstrap; 

		public unsafe BootstrapRegisterServentCommand(SOCKET socket, string socketAddress, string message, Bootstrap bootstrap)
		: base(socket){
			_bootstrap = bootstrap;
			string[] parts = message.Split(':');
			_location = parts.Length > 1 ? NormalizeLocation(parts[1]) : "";
			_address = socketAddress;
			_correct = Int16.TryParse(parts[0], out _port) && parts.Length == 2;

		}

		public static string NormalizeLocation(string location)
		{
			string[] parts = location.Split(new char[] { ',' });
			string result = "";
			for (int i = 0; i < parts.Length - 1; ++i)
				result += parts[i].Trim() + ",";
			result += parts[parts.Length - 1].Trim();
			return result;
		}

		public override void DoCommmand()
		{
			//ako parametri nisu korektni, vratiti poruku o gresci
			//zatvoriti socket
			if (!_correct) { 
				Native.SendMessage(CMD.CMD_REPLY_FAIL.ParseInt() + " " + (int) CMD.ERROR_INVALID_PARAMS, _socket);
				Native.closesocket(_socket);
				return;
			}
			Servent servent = new Servent(_address, _port, _location);


			//proveriti da li server vec postoji u listi servenata
			if (Pinger.Instance.Contains(servent))
			{
				Native.SendMessage((int)CMD.CMD_REPLY_FAIL + " " + (int)CMD.ERROR_GEOLEVEL_EXISTS, _socket);
				Native.closesocket(_socket);
				return;
			}

			//ako ne postoji dodati ga
			string[] levels = _location.Split(',');
			levels = levels.Reverse().ToArray();

			Pinger.Instance.Subscribe(servent);
			string response = " ";
			List<string> mastersToSkip = new List<string>();
			string lastLevel = null;
			for (int i = 0; i < levels.Length; i++)
			{
				List<Servent> servents = null;
				if (!_bootstrap.Masters.TryGetValue(levels[i], out servents))
				{
					_bootstrap.Masters[levels[i]] = new List<Servent>();
				}
				
				if(_bootstrap.Masters[levels[i]].Count < Properties.Settings.Default.MaxMasterServents)
				{
					/*if (i == 0)
					{
						_bootstrap.Masters[levels[i]].Add(servent);
					}*/
					Servent s = new Servent(_address, _port, SubstringFrom(_location, levels[i]));
					Console.WriteLine("Adding master for location " + s.Location);
					_bootstrap.Masters[levels[i]].Add(s);
					lastLevel = s.Location;
				}
				List<Servent> masters = _bootstrap.Masters[levels[i]];
				mastersToSkip.Add(levels[i]);
				if (lastLevel != null && levels[i].Split(',').Length > lastLevel.Split(',').Length)
					continue;
				for (int j = 0; j < masters.Count; j++)
				{
					if (response != " ")
						response += ";";
					response += masters[j].ToString();
				}
			}
			string[] lastLevelArray = lastLevel != null ? lastLevel.Split(',') : null;
			for (int i = 0; i < _bootstrap.Masters.Count; i++)
			{
				var pair = _bootstrap.Masters.ElementAt(i);
				string[] tempLevelArray = pair.Key.Split(','); 
				if (mastersToSkip.Contains(pair.Key))
					//|| (lastLevelArray != null && tempLevelArray.Length == lastLevelArray.Length && pair.Key != lastLevel))
					continue;
				for (int j = 0; j < pair.Value.Count; j++)
				{

					if (lastLevelArray != null && pair.Value[j].Location.Split(',').Length >= lastLevelArray.Length)
						continue;
					if (response != " ")
						response += ";";
					response += pair.Value[j].ToString();
				}
			}

				Native.SendMessage(CMD.CMD_REPLY_OK.ParseInt() + response, _socket);
			Native.closesocket(_socket);
		}


		public string SubstringFrom(string str, string sub)
		{
			int index = str.IndexOf(sub);
			return str.Substring(index);
		}
	}
}
